using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;

namespace CodeGenTest
{
    class Program
    {
        

        static void Main(string[] args)
        {
            //ProgramLines program = new ProgramLines();

            //Variable v1 = new Variable("v1");
            //Expr declareV1 = new DeclareVariable<int>(v1);
            //program.AddLine(declareV1);



            //Expr val1 = new Value(23);
            //Expr val2 = new Value(33);
            //Expr add1 = new AddOp(val1, val2);
            //Expr setV1 = new SetVariable(add1, v1);
            //program.AddLine(setV1);
            

            //Expr val3 = new RandomValue();
            //Expr getV1 = new GetVariable(v1);

            //Expr mul1 = new MultiPly(add1, getV1);
            //Expr add = new AddOp(val3, mul1);
            //program.AddLine(mul1);

            //Console.WriteLine("The final expr is: " );
            //Console.WriteLine(program);

            //Console.ReadKey();

            //CodeGen codeG = new CodeGen(program);
            //StandardMethod method = codeG.GetMethod();

            //Console.WriteLine("Method result: " + method());

            //Console.ReadKey();

            TestClass.TestArray();
            
        }

    }

    public class TestClass
    {
        private delegate int MethodReturnInt(int[] input);

        private delegate bool Method();
        private string Peter = "Jamen, hephey da";

        public static void TestArray()
        {
            int[] testArray = {1, 2, 3, 4, 5};


            DynamicMethod method = new DynamicMethod("Test", typeof(int), new Type[] { typeof(int[]) }, typeof(TestClass));
            ILGenerator ilg = method.GetILGenerator();
            ilg.Emit(OpCodes.Ldarg_0);
            ilg.Emit(OpCodes.Ldc_I4_5);
            ilg.Emit(OpCodes.Ldelem, typeof(int));
            ilg.Emit(OpCodes.Ret);

            MethodReturnInt mth = (MethodReturnInt)method.CreateDelegate(typeof(MethodReturnInt));
            
            
            Console.WriteLine(mth(testArray));
            Console.ReadLine();

        }


        static void Test()
        {
            DynamicMethod method = new DynamicMethod("Test", typeof(int), new Type[0], typeof(TestClass));

            ILGenerator ilg = method.GetILGenerator();

            LocalBuilder varInt = ilg.DeclareLocal(typeof(int));
            

            //ilg.Emit(OpCodes.Ldc_I4, 33);
            //ilg.Emit(OpCodes.Stloc, varInt);

            //ilg.Emit(OpCodes.Ldloc, varInt);
            //ilg.Emit(OpCodes.Isinst, typeof(int));

            ilg.Emit(OpCodes.Ldsfld, typeof(RandomValue).GetField("random"));
            ilg.EmitCall(OpCodes.Callvirt, typeof(Random).GetMethod("Next", new Type[1] { typeof(int) }), null);
            //ilg.Emit(OpCodes.Brtrue, );

            //ilg.Emit(OpCodes.Ldc_I4_2);
            //ilg.Emit(OpCodes.Add);
            ilg.Emit(OpCodes.Ret);

            Method mth = (Method)method.CreateDelegate(typeof(Method));


            Console.WriteLine("Method run: " + mth());
            Console.ReadLine();
        }
    }
}
